/*
JavaScript 的对象（Object），本质上是键值对的集合（Hash 结构），但是传统上只能用字符串当作键(数组为数字当键)。
这给它的使用带来了很大的限制。

下面代码原意是将一个 DOM 节点作为对象data的键，但是由于对象只接受字符串作为键名，
所以element被自动转为字符串[object HTMLDivElement]。
*/

const data = {};
const element = document.getElementById('myDiv');

data[element] = 'metadata';
data['[object HTMLDivElement]'] // "metadata" element被自动转为字符串[object HTMLDivElement]。

/*
为了解决这个问题，ES6 提供了 Map 数据结构。
它类似于对象，也是键值对的集合，但是“键”的范围不限于字符串，各种类型的值（包括对象）都可以当作键。
也就是说，Object 结构提供了“字符串—值”的对应，Map 结构提供了“值—值”的对应，是一种更完善的 Hash 结构实现。
如果你需要“键值对”的数据结构，Map 比 Object 更合适。

回忆java所学  map结构的特点就是key可以是任意类型 类似对象   set结构特点是有序不重复 类似数组   
操作上的一些api有所不同
*/

const m = new Map();
const o = {
	p: 'Hello World'
};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false




//作为构造函数，Map 也可以接受一个数组作为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([
	['name', '张三'],
	['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "张三"
map.has('title') // true
map.get('title') // "Author"




/*
事实上，不仅仅是数组，任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构（详见《Iterator》一章）都可以当作Map构造函数的参数。
这就是说，Set和Map都可以用来生成新的 Map。
*/
const set = new Set([
	['foo', 1],
	['bar', 2]
]);
const m1 = new Map(set);
m1.get('foo') // 1   Set和Map都可以用来生成新的 Map。

const m2 = new Map([
	['baz', 3]
]);
const m3 = new Map(m2);
m3.get('baz') // 3    Set和Map都可以用来生成新的 Map。



//如果对同一个键多次赋值，后面的值将覆盖前面的值。
const map = new Map();
map.set(1, 'aaa').set(1, 'bbb');
map.get(1) // "bbb"  



//如果读取一个未知的键，则返回undefined。
new Map().get('asfddfsasadf')
// undefined





const map = new Map();
map.set(['a'], 555);
map.get(['a']) // undefined    看似一样实则引用不相同，内存地址是不一样的  所以取不出来


const map = new Map();
const k1 = ['a']; //同样的值的两个实例(两个不同的引用)，在 Map 结构中被视为两个键。
const k2 = ['a'];
map.set(k1, 111).set(k2, 222);
map.get(k1) // 111
map.get(k2) // 222


/*
由上可知，Map 的键实际上是跟内存地址绑定的，只要内存地址不一样，就视为两个键。
这就解决了同名属性碰撞（clash）的问题，我们扩展别人的库的时候，如果使用对象作为键名，就不用担心自己的属性与原作者的属性同名。
如果 Map 的键是一个简单类型的值（数字、字符串、布尔值），则只要两个值严格相等，Map 将其视为一个键（不判断引用了）
*/

let map = new Map();

map.set(-0, 123);
map.get(+0) // 123  0和-0就是一个键

map.set(true, 1);
map.set('true', 2);
map.get(true) // 1  布尔值true和字符串true则是两个不同的键。

map.set(undefined, 3);
map.set(null, 4);
map.get(undefined) // 3   undefined和null也是两个不同的键。

map.set(NaN, 123);
map.get(NaN) // 123  虽然NaN不严格相等于自身，但 Map 将其视为同一个键。
